package com.ssy.lingxi.marketing.serviceimpl.base.coupon;

import com.ssy.lingxi.common.constant.marketing.PlatformCouponTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.marketing.entity.coupon.PlatformCouponDO;
import com.ssy.lingxi.marketing.entity.coupon.PlatformCouponHistoryDO;
import com.ssy.lingxi.marketing.model.constant.*;
import com.ssy.lingxi.marketing.model.vo.coupon.request.PlatformCouponBaseRequest;
import com.ssy.lingxi.marketing.model.vo.coupon.request.PlatformCouponPageRequest;
import com.ssy.lingxi.marketing.repository.PlatformCouponHistoryRepository;
import com.ssy.lingxi.marketing.repository.PlatformCouponRepository;
import com.ssy.lingxi.marketing.service.IProcessFeignService;
import com.ssy.lingxi.marketing.service.IScheduleFeignService;
import com.ssy.lingxi.workflow.api.model.contant.ProcessTaskStatusEnum;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 基础平台优惠券服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/10/30
 */
@Slf4j
@Service
public class BasePlatformCouponService extends BaseCouponService {

    @Resource
    private PlatformCouponRepository platformCouponRepository;
    @Resource
    private PlatformCouponHistoryRepository platformCouponHistoryRepository;
    @Resource
    private IProcessFeignService processFeignService;
    @Resource
    private IScheduleFeignService scheduleFeignService;

    /**
     * 校验优惠券参数
     * @param request 请求参数
     * @return 返回结果
     */
    protected Wrapper<Void> checkPlatformCouponParam(PlatformCouponBaseRequest request) {
        long currentTimeMillis = System.currentTimeMillis();
        // 券发放时间
        Wrapper<Void> checkReleaseTimeWrapper = this.checkReleaseTime(currentTimeMillis, request.getReleaseTimeStart(), request.getReleaseTimeEnd());
        if (ResponseCode.SUCCESS.getCode() != checkReleaseTimeWrapper.getCode()) {
            return checkReleaseTimeWrapper;
        }
        // 券有效时间
        if (PlatformCouponEffectiveTypeEnum.FIXED.getCode().equals(request.getEffectiveType())) {
            Wrapper<Void> checkEffectiveTimeWrapper = this.checkEffectiveTime(request.getReleaseTimeEnd(), request.getEffectiveTimeStart(), request.getEffectiveTimeEnd());
            if (ResponseCode.SUCCESS.getCode() != checkEffectiveTimeWrapper.getCode()) {
                return checkEffectiveTimeWrapper;
            }
        } else {
            if (Objects.isNull(request.getInvalidDay())) {
                return Wrapper.fail(ResponseCode.MARKETING_COUPON_EFFECTIVE_TIME_NOT_NULL);
            }
        }
        if (PlatformCouponTypeEnum.ZERO_DISCOUNT.getCode().equals(request.getType())) {
            // 0元抵扣券
            // 领取方式只能是营销活动用券
            if (!PlatformCouponGetWayEnum.MARKETING.getCode().equals(request.getGetWay())) {
                return Wrapper.fail(ResponseCode.MARKETING_COUPON_ZERO_DISCOUNT_MUST_MARKETING);
            }
            // 只能有一个适用商品
            if (CollectionUtils.isEmpty(request.getSuitableCommoditySkuList()) || request.getSuitableCommoditySkuList().size() != 1) {
                return Wrapper.fail(ResponseCode.MARKETING_COUPON_ZERO_DISCOUNT_COMMODITY_NOT_EMPTY);
            }
        } else {
            // 非0元抵扣券
            // 券面额不能为0
            if (BigDecimal.ZERO.equals(request.getDenomination())) {
                return Wrapper.fail(ResponseCode.MARKETING_DENOMINATION_NOT_ZERO);
            }
            // 非0元抵扣券
            // 使用条件订单金额不能为0
            if (BigDecimal.ZERO.equals(request.getUseConditionMoney())) {
                return Wrapper.fail(ResponseCode.MARKETING_USER_CONDITION_MONEY_NOT_ZERO);
            }
        }

        // 领取方式为前台用户领券, 必有领取条件
        if (PlatformCouponGetWayEnum.FRONT.getCode().equals(request.getGetWay())) {
            if (Objects.isNull(request.getConditionGetTotal()) || Objects.isNull(request.getConditionGetDay())) {
                return Wrapper.fail(ResponseCode.MARKETING_GET_WAY_POSITIVE);
            }
            if (request.getConditionGetTotal() <= 0 || request.getConditionGetDay() <= 0) {
                return Wrapper.fail(ResponseCode.MARKETING_GET_WAY_POSITIVE);
            }
            if (request.getConditionGetTotal() < request.getConditionGetDay()) {
                return Wrapper.fail(ResponseCode.MARKETING_COUPON_GET_TOTAL_GE_GET_DAY);
            }
        }
        // 使用条件金额要大于券面额
        if (request.getUseConditionMoney().compareTo(request.getDenomination()) <= 0) {
            return Wrapper.fail(ResponseCode.MARKETING_COUPON_USER_AMOUNT_CONDITION_GREATER);
        }

        return Wrapper.success();
    }

    /**
     * 公共平台优惠券分页列表
     * @param request 请求参数
     * @param statusList 状态
     * @param loginUser 登录用户信息
     * @return 返回结果
     */
    protected Page<PlatformCouponDO> basePagePlatformCoupon(PlatformCouponPageRequest request, List<Integer> statusList, UserLoginCacheDTO loginUser) {

        Pageable page = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by(request.getSortName()).descending());

        Page<PlatformCouponDO> pageList = platformCouponRepository.findAll((Specification<PlatformCouponDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            predicateList.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));

            if (Objects.nonNull(request.getId())) {
                predicateList.add(cb.equal(root.get("id"), request.getId()));
            }

            if (Objects.nonNull(request.getType())) {
                predicateList.add(cb.equal(root.get("type"), request.getType()));
            }

            if (Objects.nonNull(request.getGetWay())) {
                predicateList.add(cb.equal(root.get("getWay"), request.getGetWay()));
            }

            if (Objects.nonNull(request.getStatus())) {
                predicateList.add(cb.equal(root.get("status"), request.getStatus()));
            }

            if (!CollectionUtils.isEmpty(statusList)) {
                predicateList.add(cb.and(root.get("status").in(statusList)));
            }

            if (StringUtils.isNotEmpty(request.getName())) {
                predicateList.add(cb.like(root.get("name"), "%" + request.getName() + "%"));
            }

            if (Objects.nonNull(request.getReleaseTimeStart())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("releaseTimeStart"), request.getReleaseTimeStart()));
            }

            if (Objects.nonNull(request.getReleaseTimeEnd())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("releaseTimeEnd"), request.getReleaseTimeEnd()));
            }

            if (Objects.nonNull(request.getEffectiveTimeStart())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("effectiveTimeStart"), request.getEffectiveTimeStart()));
            }

            if (Objects.nonNull(request.getEffectiveTimeEnd())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("effectiveTimeEnd"), request.getEffectiveTimeEnd()));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        return pageList;
    }

    /**
     * 待审核平台优惠券(一级) - 提交审核
     * @param loginUser 登录用户信息
     * @param platformCouponDOList 商家活动
     * @param agree 是否同意
     * @param remark 审核意见
     */
    protected void baseAuditOnePlatformCoupon(UserLoginCacheDTO loginUser, List<PlatformCouponDO> platformCouponDOList, Integer agree, String remark) {
        for (PlatformCouponDO platformCouponDO : platformCouponDOList) {
            TaskExecuteVO executeVO = new TaskExecuteVO();
            executeVO.setProcessKey(MarketingConstants.platform_coupon_key);
            executeVO.setTaskId(platformCouponDO.getTaskId());
            executeVO.setMemberId(loginUser.getMemberId());
            executeVO.setRoleId(loginUser.getMemberRoleId());
            executeVO.setAgree(agree);
            executeVO.setDataId(platformCouponDO.getId());

            // 工作流
            Wrapper<SimpleTaskCompleteVO> result = processFeignService.completeSimpleTask(executeVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                log.error("平台优惠券审核(一级),调用工作流失败: {}", result.getMessage());
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }

            platformCouponDO.setStatus(result.getData().getStatus());
            platformCouponDO.setTaskId(result.getData().getTaskId());
            platformCouponRepository.saveAndFlush(platformCouponDO);

            // 流转记录
            PlatformCouponHistoryDO platformCouponHistoryDO = new PlatformCouponHistoryDO();
            platformCouponHistoryDO.setCouponId(platformCouponDO.getId());
            platformCouponHistoryDO.setCreateTime(System.currentTimeMillis());
            platformCouponHistoryDO.setMemberId(loginUser.getMemberId());
            platformCouponHistoryDO.setMemberName(loginUser.getCompany());
            platformCouponHistoryDO.setRoleId(loginUser.getMemberRoleId());
            platformCouponHistoryDO.setRoleName(loginUser.getMemberRoleName());
            platformCouponHistoryDO.setOperatorId(loginUser.getUserId());
            platformCouponHistoryDO.setOperatorName(loginUser.getUserName());
            platformCouponHistoryDO.setOperatorRoleName(loginUser.getUserRoleName());
            platformCouponHistoryDO.setOperatorOrgName(loginUser.getUserOrgName());
            platformCouponHistoryDO.setOperatorJobTitle(loginUser.getUserJobTitle());
            platformCouponHistoryDO.setOperation(CouponStrOperateEnum.pt_inner_examine_step1.getMessage());
            platformCouponHistoryDO.setStatus(result.getData().getStatus());
            platformCouponHistoryDO.setStatusName(PlatformCouponStatusEnum.getCodeMessage(result.getData().getStatus()));
            platformCouponHistoryDO.setRemark(remark);
            platformCouponHistoryRepository.saveAndFlush(platformCouponHistoryDO);
        }
    }

    /**
     * 待审核平台优惠券(二级) - 审核
     * @param loginUser 登录用户信息
     * @param platformCouponDOList 商家活动
     * @param agree 是否同意
     * @param remark 审核意见
     */
    protected void baseAuditTwoPlatformCoupon(UserLoginCacheDTO loginUser, List<PlatformCouponDO> platformCouponDOList, Integer agree, String remark) {
        for (PlatformCouponDO platformCouponDO : platformCouponDOList) {
            TaskExecuteVO executeVO = new TaskExecuteVO();
            executeVO.setProcessKey(MarketingConstants.platform_coupon_key);
            executeVO.setTaskId(platformCouponDO.getTaskId());
            executeVO.setMemberId(loginUser.getMemberId());
            executeVO.setRoleId(loginUser.getMemberRoleId());
            executeVO.setAgree(agree);
            executeVO.setDataId(platformCouponDO.getId());

            // 工作流
            Wrapper<SimpleTaskCompleteVO> result = processFeignService.completeSimpleTask(executeVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                log.error("平台优惠券审核(二级),调用工作流失败: {}", result.getMessage());
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }

            platformCouponDO.setStatus(result.getData().getStatus());
            platformCouponDO.setTaskId(result.getData().getTaskId());
            platformCouponRepository.saveAndFlush(platformCouponDO);

            // 流转记录
            PlatformCouponHistoryDO platformCouponHistoryDO = new PlatformCouponHistoryDO();
            platformCouponHistoryDO.setCouponId(platformCouponDO.getId());
            platformCouponHistoryDO.setCreateTime(System.currentTimeMillis());
            platformCouponHistoryDO.setMemberId(loginUser.getMemberId());
            platformCouponHistoryDO.setMemberName(loginUser.getCompany());
            platformCouponHistoryDO.setRoleId(loginUser.getMemberRoleId());
            platformCouponHistoryDO.setRoleName(loginUser.getMemberRoleName());
            platformCouponHistoryDO.setOperatorId(loginUser.getUserId());
            platformCouponHistoryDO.setOperatorName(loginUser.getUserName());
            platformCouponHistoryDO.setOperatorRoleName(loginUser.getUserRoleName());
            platformCouponHistoryDO.setOperatorOrgName(loginUser.getUserOrgName());
            platformCouponHistoryDO.setOperatorJobTitle(loginUser.getUserJobTitle());
            platformCouponHistoryDO.setOperation(CouponStrOperateEnum.pt_inner_examine_step2.getMessage());
            platformCouponHistoryDO.setStatus(result.getData().getStatus());
            platformCouponHistoryDO.setStatusName(PlatformCouponStatusEnum.getCodeMessage(result.getData().getStatus()));
            platformCouponHistoryDO.setRemark(remark);
            platformCouponHistoryRepository.saveAndFlush(platformCouponHistoryDO);
        }
    }

    /**
     * 待提交平台优惠券 - 提交
     * @param loginUser 登录用户信息
     * @param platformCouponDOList 商家活动
     */
    protected void baseSubmitPlatformCoupon(UserLoginCacheDTO loginUser, List<PlatformCouponDO> platformCouponDOList) {
        long currentTimeMillis = System.currentTimeMillis();
        for (PlatformCouponDO platformCouponDO : platformCouponDOList) {
            TaskExecuteVO executeVO = new TaskExecuteVO();
            executeVO.setProcessKey(MarketingConstants.platform_coupon_key);
            executeVO.setTaskId(platformCouponDO.getTaskId());
            executeVO.setMemberId(loginUser.getMemberId());
            executeVO.setRoleId(loginUser.getMemberRoleId());
            executeVO.setAgree(ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
            executeVO.setDataId(platformCouponDO.getId());

            // 工作流
            Wrapper<SimpleTaskCompleteVO> result = processFeignService.completeSimpleTask(executeVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                log.error("平台优惠券提交,调用工作流失败: {}", result.getMessage());
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }

            platformCouponDO.setStatus(result.getData().getStatus());
            platformCouponDO.setTaskId(result.getData().getTaskId());
            platformCouponRepository.saveAndFlush(platformCouponDO);

            // 流转记录
            PlatformCouponHistoryDO platformCouponHistoryDO = new PlatformCouponHistoryDO();
            platformCouponHistoryDO.setCouponId(platformCouponDO.getId());
            platformCouponHistoryDO.setCreateTime(System.currentTimeMillis());
            platformCouponHistoryDO.setMemberId(loginUser.getMemberId());
            platformCouponHistoryDO.setMemberName(loginUser.getCompany());
            platformCouponHistoryDO.setRoleId(loginUser.getMemberRoleId());
            platformCouponHistoryDO.setRoleName(loginUser.getMemberRoleName());
            platformCouponHistoryDO.setOperatorId(loginUser.getUserId());
            platformCouponHistoryDO.setOperatorName(loginUser.getUserName());
            platformCouponHistoryDO.setOperatorRoleName(loginUser.getUserRoleName());
            platformCouponHistoryDO.setOperatorOrgName(loginUser.getUserOrgName());
            platformCouponHistoryDO.setOperatorJobTitle(loginUser.getUserJobTitle());
            platformCouponHistoryDO.setOperation(CouponStrOperateEnum.pt_inner_submit.getMessage());
            platformCouponHistoryDO.setStatus(result.getData().getStatus());
            platformCouponHistoryDO.setStatusName(PlatformCouponStatusEnum.getCodeMessage(result.getData().getStatus()));
            platformCouponHistoryRepository.saveAndFlush(platformCouponHistoryDO);

            if (platformCouponDO.getReleaseTimeStart() > currentTimeMillis) {
                // 定时发券开始
                scheduleFeignService.createPfCouponReleaseStartTask(loginUser, platformCouponDO);

                // 定时发券结束
                scheduleFeignService.createPfCouponReleaseEndTask(loginUser, platformCouponDO);
            } else if (platformCouponDO.getReleaseTimeStart() < currentTimeMillis
                    && platformCouponDO.getReleaseTimeEnd() > currentTimeMillis) {

                platformCouponDO.setStatus(PlatformCouponStatusEnum.EXECUTING.getCode());
                platformCouponRepository.saveAndFlush(platformCouponDO);

                // 定时发券结束
                scheduleFeignService.createPfCouponReleaseEndTask(loginUser, platformCouponDO);
            } else if (platformCouponDO.getReleaseTimeEnd() < currentTimeMillis){

                platformCouponDO.setStatus(PlatformCouponStatusEnum.FINISH.getCode());
                platformCouponRepository.saveAndFlush(platformCouponDO);
            }
        }
    }
}